package cn.zhagzheguo.xk.util.excel;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 主要的parser类、
 * 
 * @author zhagz
 * 
 */
public class XlsParser {

	/**
	 * 存储最后从表中得到的所有object对象/行
	 */
	private List<Object> data = new ArrayList<>();

	/**
	 * xls存储路径
	 */
	private String xlsPath = null;

	/**
	 * 第一列存名字-->>map.put(1,"name");
	 * 
	 */
	private Map<Integer, String> map;
	/**
	 * model对象
	 */
	private Class clazz;

	/**
	 * 显示是否已经进行操作完毕
	 */
	private boolean isFinished = false;

	/****************************************************/
	// 可设置变量
	/**
	 * 遍历开始行
	 */
	private int startRow = 0;
	/**
	 * 遍历结束行
	 */
	private int lastRow = -1;

	private XlsParser() {
	}

	/**
	 * 
	 * @param xlsPath
	 *            xls路径
	 * @param map
	 *            clazz中属性和xls列号对应关系
	 * @param clazz
	 *            与xls对应的model类
	 */
	public XlsParser(String xlsPath, Map<Integer, String> map, Class clazz) {
		checkAllParam(xlsPath, map, clazz);
		this.xlsPath = xlsPath;
		this.clazz = clazz;
		this.map = map;
	}

	/**
	 * 检查所有变量，正确性
	 */
	private void checkAllParam(String xlsPath, Map<Integer, String> map, Class clazz) {
		File file = new File(xlsPath);
		if (!file.isFile() || !file.exists()) {
			throw new RuntimeException("[Error] File " + xlsPath + " is not a file or does not exist.");
		}
		if (map == null) {
			throw new NullPointerException("[Error] Map is null ?");
		}
		if (clazz == null) {
			throw new NullPointerException("[Error] Class " + clazz.getName() + " is null ?");
		}

	}

	/**
	 * 得到文件后缀
	 * 
	 * @return
	 */
	private String getFileSuffix() {
		return xlsPath.substring(xlsPath.lastIndexOf(".") + 1);
	}

	/**
	 * 根据getFileSuffix识别出的文件类别进行解析。
	 */
	private void dispatcher() {
		switch (getFileSuffix()) {
		case ExcelType.XLS_BELOW2007:
			doParse_below2007();
			break;
		case ExcelType.XLSX_ABOVE2007:
			doParse_Above2007();
			break;
		default:
			// 格式不对，报错
			throw new RuntimeException("[Error] Wrong file format," + ExcelType.XLS_BELOW2007 + ","
					+ ExcelType.XLSX_ABOVE2007 + " instead.");
		}
		isFinished = true;
	}

	private void doParse_below2007() {
		File file = new File(xlsPath);

		try {
			HSSFWorkbook workbook = new HSSFWorkbook(FileUtils.openInputStream(file));
			HSSFSheet sheet = workbook.getSheetAt(0);

			/**
			 * 如果lastRow未赋值，则使用默认值
			 */
			int lastRowNum = (lastRow == -1 ? sheet.getLastRowNum() : lastRow);

			/* 遍历行 */
			for (int i = startRow; i < lastRowNum + 1; i++) {
				HSSFRow row = sheet.getRow(i);

				// 一个invoker最后返回一个对象
				Invoker invoker = new Invoker(clazz);

				// 解析map，从map映射到实体并进行操作。
				Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<Integer, String> entry = (Map.Entry<Integer, String>) it.next();
					Integer column = entry.getKey();
					String propertyName = entry.getValue();

					/* 对cell进行操作 */
					HSSFCell cell = row.getCell(column - 1);
					Object propertyValue = null;
					if (cell != null) {
						int cellType = cell.getCellType();
						switch (cellType) {
						case Cell.CELL_TYPE_BOOLEAN:
							propertyValue = cell.getBooleanCellValue();
							break;
						case Cell.CELL_TYPE_ERROR:
							propertyValue = cell.getErrorCellValue();
							break;
						case Cell.CELL_TYPE_FORMULA:
							propertyValue = cell.getCellFormula();
							break;
						case Cell.CELL_TYPE_NUMERIC:
							propertyValue = cell.getNumericCellValue();
							break;
						case Cell.CELL_TYPE_STRING:
							propertyValue = cell.getStringCellValue();
							break;
						case Cell.CELL_TYPE_BLANK:
							propertyValue = cell.toString();
							break;
						default:
							break;
						}
					}
					if (propertyValue != null) {
						invoker.setProperty(propertyName, propertyValue);
					}
				}
				// 一个while代表一行，一行结束后保存一个对象
				data.add(invoker.returnObject());
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void doParse_Above2007() {
		File file = new File(xlsPath);

		try {
			XSSFWorkbook workbook = new XSSFWorkbook(FileUtils.openInputStream(file));
			XSSFSheet sheet = workbook.getSheetAt(0);

			/**
			 * 如果lastRow未赋值，则使用默认值
			 */
			int lastRowNum = (lastRow == -1 ? sheet.getLastRowNum() : lastRow);

			/* 遍历行 */
			for (int i = startRow; i < lastRowNum + 1; i++) {
				XSSFRow row = sheet.getRow(i);

				// 一个invoker最后返回一个对象
				Invoker invoker = new Invoker(clazz);

				// 解析map，从map映射到实体并进行操作。
				Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<Integer, String> entry = (Map.Entry<Integer, String>) it.next();
					Integer column = entry.getKey();
					String propertyName = entry.getValue();

					/* 对cell进行操作 */
					XSSFCell cell = row.getCell(column - 1);
					Object propertyValue = null;
					if (cell != null) {
						int cellType = cell.getCellType();
						switch (cellType) {
						case Cell.CELL_TYPE_BOOLEAN:
							propertyValue = cell.getBooleanCellValue();
							break;
						case Cell.CELL_TYPE_ERROR:
							propertyValue = cell.getErrorCellValue();
							break;
						case Cell.CELL_TYPE_FORMULA:
							propertyValue = cell.getCellFormula();
							break;
						case Cell.CELL_TYPE_NUMERIC:
							propertyValue = cell.getNumericCellValue();
							break;
						case Cell.CELL_TYPE_STRING:
							propertyValue = cell.getStringCellValue();
							break;
						case Cell.CELL_TYPE_BLANK:
							propertyValue = cell.toString();
							break;
						default:
							break;
						}
					}
					// 是null跳过就行了
					if (propertyValue != null) {
						invoker.setProperty(propertyName, propertyValue);
					}
				}
				// 一个while代表一行，一行结束后保存一个对象
				data.add(invoker.returnObject());
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 开始解析excel，解析完成后返回list
	 * 
	 * @return
	 */
	public List<Object> parse() {
		dispatcher();
		if (isFinished) {
			return data;
		}
		return null;
	}

	/**
	 * 设置开始行数，默认为0
	 * 
	 * @param startRow
	 */
	public void setStartRow(int startRow) {
		// 注意，在程序里是默認從0开始，因此需要-1
		this.startRow = startRow - 1;
	}

	/**
	 * 设置结束行数，默认为到最后一行没有数据的行为止
	 * 
	 * @param lastRow
	 */
	public void setLastRow(int lastRow) {
		// 注意，在程序里是默認從0开始，因此需要-1
		this.lastRow = lastRow - 1;
	}

}
